package com.cius.dao;

import com.cius.model.PageModel;
import com.cius.util.GenericsUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * Dao支持类
 * Created by ciuscheung on 16/9/22.
 */

@Transactional
public class DaoSupport<T> implements BaseDao<T> {

    //范性的类型
    protected Class<T> entityClass = GenericsUtils.getGenericType(this.getClass());


    /**
     * 利用sava()方法保存对象的详细信息
     * @param obj
     */
    @Override
    public void save(Object obj) {
        getSession().save(obj);
    }

    @Override
    public void saveOrUpdate(Object obj) {
        getSession().saveOrUpdate(obj);
    }

    @Override
    public void update(Object obj) {
        getSession().update(obj);
    }

    @Override
    public void delete(Serializable... ids) {
        for(Serializable id : ids){
            T t = (T) getSession().load(this.entityClass,id);
            getSession().delete(t);
        }
    }


    //利用get()方法加载对象，获取对象详细信息
    @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
    @Override
    public T get(Serializable entityId) {
        return (T) getSession().get(this.entityClass,entityId);
    }

    //利用load()方法加载对象，获取对象详细信息
    @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
    @Override
    public T load(Serializable entityId) {
        return (T) getSession().load(this.entityClass,entityId);
    }

    //利用hql语句查找单条信息
    @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
    @Override
    public Object uniqueResult(final String hql, final Object[] queryParams) {
        Query query = getSession().createQuery(hql);
        setQueryParams(query,queryParams);//设置查询参数
        return query.uniqueResult();
    }

    /**
     * 获取指定对象的信息条数
     * @return
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
    @Override
    public long getCount() {
        String hql = "select count(*) from" + GenericsUtils.getGenericName(this.entityClass);
        return (Long) uniqueResult(hql,null);
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
    @Override
    public PageModel<T> find(int pageNo, int maxResult) {
        return find(null,null,null,pageNo,maxResult);
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
    @Override
    public PageModel<T> find(int pageNo, int maxResult, String where, Object[] queryParams) {
        return find(where,queryParams,null,pageNo,maxResult);
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
    @Override
    public PageModel<T> find(int pageNo, int maxResult, Map<String, String> orderBy) {
        return find(null,null,orderBy,pageNo,maxResult);
    }


    /**
     * 分页查询
     * @param where 查询条件
     * @param queryParams hql参数值
     * @param orderBy 排序
     * @param pageNo 第几页
     * @param maxResult 返回记录数量
     * @return PageModel
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
    @Override
    public PageModel<T> find(final String where, final Object[] queryParams, final Map<String, String> orderBy, final int pageNo, final int maxResult) {
        final PageModel<T> pageModel = new PageModel<T>();//实例化分页对象
        pageModel.setPageNo(pageNo);//设置当前页数
        pageModel.setPageSize(maxResult);//设置每页现实记录数
        String hql = new StringBuffer().append("from")//添加from字段
                .append(GenericsUtils.getGenericName(entityClass))//添加对象类型
                .append(" ")//添加空格
                .append(where == null ? "" : where)//如果where为null就添加空格，反之添加where
                .append(createOrderBy(orderBy))//添加排序条件参数
                .toString();//转化为字符串
        Query query = getSession().createQuery(hql);//执行查询
        setQueryParams(query,queryParams);//为参数赋值
        List<T> list = null;//定义List对象
        //如果maxResult<0，则查询所有
        if(maxResult < 0 && pageNo < 0){
            list = query.list();//将查询结果转化为List对象
        }
        else {
            list = query.setFirstResult(getFirstResult(pageNo,maxResult))//设置分页起始位置
                    .setMaxResults(maxResult)//设置每页现实的记录数
                    .list();//将结果转化为List对象
            hql = new StringBuffer().append("select count(*) from")//添加hql语句
                    .append(GenericsUtils.getGenericName(entityClass))//添加对象类型
                    .append(" ")//添加空格
                    .append(where == null ? "" : where)//如果where为null就添加空格,反之添加where
                    .toString();//转化为字符串
            query = getSession().createQuery(hql);//执行查询
            setQueryParams(query,queryParams);//设置hql参数
            int totalRecords = ((Long) query.uniqueResult()).intValue();//类型转换
            pageModel.setTotalRecords(totalRecords);//设置总记录数
        }
        pageModel.setList(list);//将查询的list对象放入实体对象中
        return pageModel;//返回分页的实体对象
    }


    /**
     * 获取分页查询中的结果集的起始位置
     * @param pageNo 第几页
     * @param maxResult 页面现实的记录数
     * @return 起始位置
     */
    protected int getFirstResult(int pageNo,int maxResult){
        int firstResult = (pageNo -1) * maxResult;
        return firstResult <0 ? 0 : firstResult;
    }

    /**
     * 对query中的参数赋值
     * @param query
     * @param queryParams
     */
    protected void setQueryParams(Query query,Object[] queryParams){
        if(queryParams != null && queryParams.length>0){
            for (int i = 0; i < queryParams.length; i++) {
                query.setParameter(i,queryParams[i]);
            }
        }
    }

    /**
     * 创建排序hql语句
     * @param orderBy
     * @return 排序字符串
     */
    protected String createOrderBy(Map<String,String> orderBy){
        StringBuffer sb = new StringBuffer("");
        if(orderBy != null && orderBy.size()>0){
            sb.append(" order by ");
            for (String key : orderBy.keySet()){
                sb.append(key).append(" ").append(orderBy.get(key)).append(",");
            }
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    /**
     * 获取Session对象
     * @return
     */
    @Autowired
    @Qualifier("sessionFactory")
    private SessionFactory sessionFactory;
    protected Session getSession(){
        return sessionFactory.getCurrentSession();
    }
}
